/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hoja5;


import java.lang.reflect.Array;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Random;
import java.util.ArrayDeque;

/**
 * 
 * @author ennio
 */
public class Probando_Banco {
    private static int hacer;
    private static int tiempo_banco_abierto=1;
    private static int indice_personas=0;
    private static int personas_salidas_banco=0;
    private static int suma_tiempo_personas=0;
    private static int max_personas=10;//cantidad de personas que entran al banco
    private static int rangoT1=20;//hora de llegada (min)
    private static int rangoT2=30;//tiempo de transacción (min)

    private static String imprimir1="",imprimir2="",imprimir3="",personas_modificadas="",fila_corta="";

    private static Scanner scan = new Scanner(System.in);
    private static ArrayList<Interfaz_cola<Persona>>Colas=new ArrayList<Interfaz_cola<Persona>>();
    private static ArrayList<Persona> Personas = new ArrayList<Persona>();

    private static ArrayList<Evento> Eventos= new ArrayList<Evento>();
   
    //método main donde empieza la ejecución del programa
    /**
     * 
     * @param args
     */
    public static void main(String args[])
    {
        System.out.println("\n**************************************************\n");
        System.out.println("               Bienvenido al Banco\n");
        System.out.println("**************************************************");
               for (int i=0;i<4;i++)//*****************************************************************************************************************
        {
            //Colas.add(new Cola_implementacion_arreglo<Persona>()); // ** PRIMERA IMPLEMENTACIÓN: ARREGLOS ********
            Colas.add(new Cola_implementacion_lista<Persona>()); // **** SEGUNDA IMPLEMENTAICÓN: LISTA ENCADENADA **
            //Colas.add(new Cola_implementacion_JCF<Persona>()); // **** SEGUNDA IMPLEMENTAICÓN: LISTA ENCADENADA **
        }
               Personas_Random();
               do
        {
            Menu();
        } while (hacer!=4);//hasta que precione salir
        System.out.println("\n\n¡Gracias por utilizar el programa!");
    }

    //método que despliega el menú para realizar la acción del usuario ****************************
    /**
     * 
     */
    public static void Menu(){
        do //ciclo hasta que ingrese bien una acción a realizar
        {
            System.out.println("\n\t** Menu Principal del Banco **");
            System.out.println("1- Ver próximos n minutos");
            System.out.println("2- Ver estado de todas las personas");
            System.out.println("3- Ver eventos transcurridos hasta el momento");
            System.out.println("4- Salir del Programa");
            System.out.print("\t¿Qué desea hacer?\tMarque el número: ");
            //despliega mensaje de error si no escoje una opcion del menu principal
            try{
                hacer=scan.nextInt();
            }
            catch(Exception exp){ //para prevenir el ingreso de algún caracter diferente a número
                System.out.println("¡Error accion no válida!\n");
                hacer=-1;
            }
            scan.nextLine();
            if ((hacer<1 || hacer>4) &&(hacer!=-1))
                System.out.println("¡Error accion fuera de las opciones!\n");

        } while (hacer<1 || hacer>4);
        System.out.println("\n\n");
        //para realizar la accion marcada arriba
        switch (hacer)
        {
            case 1://  ********* VER PRÓXIMOS 10 MINUTOS ***********************************************
                int cant_tiempo=0;
                do{
                    try{
                        System.out.print("Ingrese cuántos minutos desea ver: ");
                        cant_tiempo=Integer.parseInt(scan.nextLine());
                        break;
                    }
                    catch(Exception exp){System.out.println("Ingresó mal el número, vuelva a ingresarlo");}
                }while(true);
                boolean imprime=false;
                do{
                    try
                    {
                        System.out.print("¿Desea imprimir el detalle por minuto?\n1- Sí\n2- No\n\tSeleccione un número: ");
                        int a=Integer.parseInt(scan.nextLine());
                        if (a==1){
                            imprime=true;
                            break;
                        }
                        else if (a==2){
                            imprime=false;
                            break;
                        }
                        else
                            System.out.println("Ingresó mal el número, vuelva a ingresarlo");
                    }
                    catch(Exception exp){System.out.println("Ingresó mal el número, vuelva a ingresarlo");}
                }while(true);

                Evento_de_tiempo(cant_tiempo,imprime);
                break;
                
            case 2://  ********* VER ESTADO PERSONAS **************************************************
                //ciclo para imprimr estado de las personas
                for (int i=0;i<Personas.size()-1;i++)
                {
                    System.out.println(Personas.get(i).getNombre()+" "+Personas.get(i).toString());
                }
                break;
            case 3://  ********* VER LISTA DE EVENTOS **************************************************
                System.out.println("\n");
                if (Eventos.size()==0){
                    System.out.println("\n******************************************" +
                                        " Todavía no se ha presentado ningún evento...\n" +
                                         "******************************************");
                }
                for(int i=0;i<Eventos.size();i++)
                    System.out.println(Eventos.get(i));
                break;
        }
    }
    //método para generar los valores random de las personas
    /**
     * 
     */
    public static void Personas_Random(){
        
        Personas = new ArrayList<Persona>();

        Random rnd = new Random();

        int t1=rnd.nextInt(rangoT1)+1;//número random entre 1-480
        int t2=rnd.nextInt(rangoT2)+1;//número random entre 1-30//TODO regresar esto

        Integer[] t1s= new Integer[max_personas+1];

        for (int i=0;i<max_personas+1;i++){
            t1=rnd.nextInt(rangoT1)+1;//número random entre 1-480
            t1s[i]=t1;
            for(int j=0;j<i;j++){//ciclo para que no sean repetidos los números
                if(t1s[j]==t1s[i]){
                    i--;
                    break;
                }
            }

        }
        Sorting.selectionSort(t1s);
        for (int i=0;i<max_personas+1;i++){
            t2=rnd.nextInt(rangoT2)+1;//número random entre 1-30//TODO regersar esto
            Personas.add( (new Persona((int)t1s[i],t2,("P"+(i+1))))  );
        }
    }


    /**
     * 
     * @param cant_mins
     * @param imprime
     */
    public static void Evento_de_tiempo(int cant_mins,boolean imprime){

        for(int i=0;i<cant_mins;i++){
            imprimir1="";
            imprimir2="";
            imprimir3="";
            personas_modificadas="";
            fila_corta="";

            if (personas_salidas_banco==Personas.size()-1){
                System.out.println("******************************************\nEl promedio de tiempo por persona es: "+((double)(suma_tiempo_personas)/(double)(Personas.size())-1)+"\n*******************************************");
                break;
            }
            else if(indice_personas!=Personas.size()-1)//significa que hay personas fuera de las colas o del banco
            {
                //System.out.println("Todavía hay personas pendiente de que hagan cola");//TODO quitar esto:...
                Evento_de_entrada();
                imprimir2+="Todavía no han entrado "+(Personas.size()-indice_personas)+" personas";
            }
            else
            {
                imprimir2+="Ya entraron las "+(Personas.size()-1)+" personas";
                //System.out.println("Todas las personas ya se encuentran haciendo cola");//TODO quitar esto...
            }
            
            Evento_de_salida();
            if (imprime==true){
                System.out.println(Imprimir_Evento());
            }
            tiempo_banco_abierto++;

        }

    }

    //cuando una persona (o varias) llegan y quieren hacer cola
    /**
     * 
     */
    public static void Evento_de_entrada(){
        if(Personas.get(indice_personas).getT1()!=tiempo_banco_abierto)//si es diferente significa que ninguno ha entrado a esa hora
            imprimir3+="ninguna";//System.out.println("Ninguna persona hace cola a esta hora");

        else if(indice_personas>=Personas.size()){//Significa que ya no hay personas fuera del banco o de la fila
            System.out.println("Ya no hay personas fuera de la fila...");//TODO quitar esto, posiblemente
        }
        else
        {
            imprimir3+="1\nPersona entrante: "+Personas.get(indice_personas).getNombre()+" "+Personas.get(indice_personas);
            int fila_mas_corta=0;
            int menor_cantidad=Colas.get(0).getDisponibles();

            //revisa qué cola es la más corta
            if(Colas.get(1).getDisponibles()>menor_cantidad)
            {
                    menor_cantidad=Colas.get(1).getDisponibles();
                    fila_mas_corta=1;
            }
            if (Colas.get(2).getDisponibles()>menor_cantidad)
            {
                    menor_cantidad=Colas.get(2).getDisponibles();
                    fila_mas_corta=2;
            }
            if (Colas.get(3).getDisponibles()>menor_cantidad)
            {
                    menor_cantidad=Colas.get(3).getDisponibles();
                    fila_mas_corta=3;
            }
            
            Personas.get(indice_personas).setFila(fila_mas_corta+1);//+1 para que no empiece en 0, sino en 1
            Colas.get(fila_mas_corta).push( Personas.get(indice_personas) );
            //agreaga a la lista de eventos
            Eventos.add(new Evento_Entrada("\n\tTiempo: "+tiempo_banco_abierto+" Datos de la persona:  Nombre:"+Personas.get(indice_personas).getNombre()+" "+Personas.get(indice_personas)));

            fila_corta+="Ésta persona entra en la ventanilla: "+(fila_mas_corta+1)+"\n";

            indice_personas++;
            
        }
    }

    //cuando una persona termina de ser atendida
    /**
     * 
     */
    public static void Evento_de_salida(){
        //***** referente a la ventanilla 1 *************************************
        try{
            imprimir1+="* Ventanilla 1: ";
            Colas.get(0).primera_Posicion().setT2(Colas.get(0).primera_Posicion().getT2()-1);
            personas_modificadas+=""+Colas.get(0).primera_Posicion().getNombre()+": "+Colas.get(0).primera_Posicion().toString()+"\n";
            if (Colas.get(0).primera_Posicion().getT2()==0){
                imprimir1+="Salió "+Colas.get(0).primera_Posicion().getNombre()+" de esta ventanilla";

                suma_tiempo_personas+=((tiempo_banco_abierto-(Colas.get(0).primera_Posicion().getT1())));
                Colas.get(0).primera_Posicion().setHora_salida(tiempo_banco_abierto);
                //System.out.println("Salió la persona de la ventanilla 1");
                
                //agrega otro evento de salida
                Eventos.add(new Evento_Salida("\n\tTiempo: "+tiempo_banco_abierto+" Datos de la persona: Nombre:"+Colas.get(0).primera_Posicion().getNombre()+": "+Colas.get(0).primera_Posicion().toString()));
                
                Colas.get(0).pop();//sale la persona
                personas_salidas_banco++;

            }
            else
                imprimir1+="Atendiendo a "+Colas.get(0).primera_Posicion().getNombre()+"";
        }
        catch(Exception ex){imprimir1+="vacía\t\t";}//System.out.println("No hay nadie en la ventanilla 1");}
        imprimir1+="\t-> Personas adentro: "+(10-Colas.get(0).getDisponibles())+"\n";


        //***** referente a la ventanilla 2 *************************************
        try{
            imprimir1+="* Ventanilla 2: ";
            Colas.get(1).primera_Posicion().setT2(Colas.get(1).primera_Posicion().getT2()-1);
            personas_modificadas+=""+Colas.get(1).primera_Posicion().getNombre()+": "+Colas.get(1).primera_Posicion().toString()+"\n";
            if (Colas.get(1).primera_Posicion().getT2()==0){
                imprimir1+="Salió "+Colas.get(1).primera_Posicion().getNombre()+" de esta ventanilla";
                suma_tiempo_personas+=(tiempo_banco_abierto-Colas.get(1).primera_Posicion().getT1());
                Colas.get(1).primera_Posicion().setHora_salida(tiempo_banco_abierto);

                //agrega otro evento de salida
                Eventos.add(new Evento_Salida("\n\tTiempo: "+tiempo_banco_abierto+" Datos de la persona: Nombre:"+Colas.get(1).primera_Posicion().getNombre()+": "+Colas.get(1).primera_Posicion().toString()));

                //System.out.println("Salió la persona de la ventanilla 2");
                Colas.get(1).pop();
                personas_salidas_banco++;
            }
            else
                imprimir1+="Atendiendo a "+Colas.get(1).primera_Posicion().getNombre()+"";
        }
        catch(Exception ex){imprimir1+="vacía\t\t";}//{System.out.println("No hay nadie en la ventanilla 2");}
        imprimir1+="\t-> Personas adentro: "+(10-Colas.get(1).getDisponibles())+"\n";

        //***** referente a la ventanilla 3 *************************************
        try{
            imprimir1+="* Ventanilla 3: ";
            Colas.get(2).primera_Posicion().setT2(Colas.get(2).primera_Posicion().getT2()-1);
            personas_modificadas+=""+Colas.get(2).primera_Posicion().getNombre()+": "+Colas.get(2).primera_Posicion().toString()+"\n";
            if (Colas.get(2).primera_Posicion().getT2()==0){
                imprimir1+="Salió "+Colas.get(2).primera_Posicion().getNombre()+" de esta ventanilla";
                suma_tiempo_personas+=(tiempo_banco_abierto-Colas.get(2).primera_Posicion().getT1());
                Colas.get(2).primera_Posicion().setHora_salida(tiempo_banco_abierto);

                //agrega otro evento de salida
                Eventos.add(new Evento_Salida("\n\tTiempo: "+tiempo_banco_abierto+" Datos de la persona: Nombre:"+Colas.get(2).primera_Posicion().getNombre()+": "+Colas.get(2).primera_Posicion().toString()));

                Colas.get(2).pop();
                personas_salidas_banco++;
            }
            else
                imprimir1+="Atendiendo a "+Colas.get(2).primera_Posicion().getNombre()+"";
        }
        catch(Exception ex){imprimir1+="vacía\t\t";}//{System.out.println("No hay nadie en la ventanilla 3");}
        imprimir1+="\t-> Personas adentro: "+(10-Colas.get(2).getDisponibles())+"\n";


        //***** referente a la ventanilla 4 *************************************
        try{
            imprimir1+="* Ventanilla 4: ";
            Colas.get(3).primera_Posicion().setT2(Colas.get(3).primera_Posicion().getT2()-1);
            personas_modificadas+=""+Colas.get(3).primera_Posicion().getNombre()+": "+Colas.get(3).primera_Posicion().toString()+"\n";
            if (Colas.get(3).primera_Posicion().getT2()==0){
                imprimir1+="Salió "+Colas.get(3).primera_Posicion().getNombre()+" de esta ventanilla";
                suma_tiempo_personas+=(tiempo_banco_abierto-Colas.get(3).primera_Posicion().getT1());
                Colas.get(3).primera_Posicion().setHora_salida(tiempo_banco_abierto);

                //agrega otro evento de salida
                Eventos.add(new Evento_Salida("\n\tTiempo: "+tiempo_banco_abierto+" Datos de la persona: Nombre:"+Colas.get(3).primera_Posicion().getNombre()+": "+Colas.get(3).primera_Posicion().toString()));

                Colas.get(3).pop();
                personas_salidas_banco++;
            }
            else
                imprimir1+="Atendiendo a "+Colas.get(3).primera_Posicion().getNombre()+"";
        }
        catch(Exception ex){imprimir1+="vacía\t\t";}//{System.out.println("No hay nadie en la ventanilla 4");}
        imprimir1+="\t-> Personas adentro: "+(10-Colas.get(3).getDisponibles())+"\n";


        //***********************************************************************
        
    }

    //para imprimir lo ocurrido en cada evento
    /**
     * 
     * @return
     */
    public static String Imprimir_Evento(){
        String temporal="************ TIEMPO "+tiempo_banco_abierto+" (min) **************\n";
        imprimir3="Personas que entran al banco a esta hora: "+imprimir3;
        temporal+=imprimir3+"\n";
        temporal+=fila_corta+"\n";//contiene en la fila que se está entrando la persona que ingresa
        temporal+="\nVENTANILLAS:\n";
        temporal+=imprimir1+"\n";//contiene la información de ventanillas
        temporal+=personas_modificadas+"\n";
        temporal+=imprimir2+"\n";//contiene si todavía falta gente por entrar
        temporal+="******************************************\n";
        return temporal;
    }

}